﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace AstoriaPlus
{
	/// <summary>
	/// Default implementation of <see cref="IPipelineContext"/>.
	/// </summary>
	public class PipelineContext : IPipelineContext
	{
		private Dictionary<Type, object> values = new Dictionary<Type, object>();

		/// <summary>
		/// Determines whether the context contains an entry of the given type <typeparamref name="T"/>.
		/// </summary>
		public bool Has<T>()
		{
			return this.values.ContainsKey(typeof(T));
		}

		/// <summary>
		/// Gets the entry of the given type <typeparamref name="T"/>.
		/// </summary>
		public T Get<T>()
		{
			object entry;
			if (this.values.TryGetValue(typeof(T), out entry))
				return (T)entry;
			else
				return default(T);
		}

		/// <summary>
		/// Gets the value of the entry of the given type <typeparamref name="T"/>.
		/// </summary>
		public void Set<T>(T value)
		{
			if (value != null)
				this.values[typeof(T)] = value;
			else
				this.values.Remove(typeof(T));
		}

		/// <summary>
		/// Determines whether the context contains an entry of the given type <typeparamref name="T"/>
		/// and key.
		/// </summary>
		public bool Has<T>(object key)
		{
			if (!this.values.ContainsKey(typeof(T)))
				return false;

			var indexed = (Dictionary<object, T>)this.values[typeof(T)];

			return indexed.ContainsKey(key);
		}

		/// <summary>
		/// Gets the entry of the given type <typeparamref name="T"/> and key.
		/// </summary>
		public T Get<T>(object key)
		{
			if (!this.values.ContainsKey(typeof(T)))
				return default(T);

			var indexed = (Dictionary<object, T>)this.values[typeof(T)];

			T entry;
			if (indexed.TryGetValue(key, out entry))
				return entry;
			else
				return default(T);
		}

		/// <summary>
		/// Sets the value of the entry of the given type <typeparamref name="T"/> and key.
		/// </summary>
		public void Set<T>(object key, T value)
		{
			if (!this.values.ContainsKey(typeof(T)))
				this.values[typeof(T)] = new Dictionary<object, T>();

			var indexed = (Dictionary<object, T>)this.values[typeof(T)];

			if (value == null)
				indexed.Remove(key);
			else
				indexed[key] = value;
		}
	}
}